package com.vichat.common.rudp;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;

public class RudpMonitorUtil {
    public static boolean monitorFlag = false;
    public static long receiveThreadNum = 0;
    public static long recvBlockNum = 0;
    public static long recvAckNum = 0;
    public static long errAckNum = 0;
    public static long recvBlockCost = 0;
    public static long maxRecvBlockCost = 0;
    public static long minRecvBlockCost = 999;
    public static long busiThreadNum = 0;
    public static long busiStartNum = 0;
    public static long busiDoneNum = 0;
    public static long busiEndNum = 0;
    public static long busiNum = 0;
    public static long busiCosts = 0;
    public static long maxBusiCosts = 0;
    public static long minBusiCost = 999;

    public static long sndBlockNum = 0;
    public static long sndBlockAckNum = 0;
    public static long resendBlockNum = 0;
    public static long expireBlockNum = 0;

    public static long transNum = 0;
    public static long transExpireNum = 0;
    public static long transCosts = 0;
    public static long maxTransCost = 0;
    public static long minTransCost = 999;

    public static long perfBusiNum = 0;
    public static long goodBusiNum = 0;
    public static long comBusiNum = 0;
    public static long slowBusiNum = 0;
    public static long badBusiNum = 0;


    private static transient Logger logger = LoggerFactory.getLogger(RudpMonitorUtil.class);

    private static HashMap<String, TransMonitor> monitorMap = new HashMap<String, TransMonitor>();


    public synchronized static void sendBlock() {
        sndBlockNum++;
    }

    public static void receiveAck() {
        sndBlockAckNum++;
    }

    public static void errorAck() {
        errAckNum++;
    }

    public static void resendBlock() {
        resendBlockNum++;
    }

    public static void expireBlock() {
        expireBlockNum++;
    }

    public synchronized static void startReceiveThread() {
        receiveThreadNum++;

    }

    public synchronized static void endReceiveThread(long costtime, int msgtype) {
        receiveThreadNum--;
        if (msgtype == 1) {
            recvAckNum++;
        } else {
            recvBlockNum++;
            recvBlockCost += costtime;
            maxRecvBlockCost = costtime > maxRecvBlockCost ? costtime : maxRecvBlockCost;
            minRecvBlockCost = costtime < minRecvBlockCost ? costtime : minRecvBlockCost;
        }
    }


    public synchronized static void startBusiThread() {
        busiThreadNum++;
        busiDoneNum++;
    }

    public synchronized static void endBusiThread(long costtime) {
        busiThreadNum--;
        busiStartNum--;

        if (busiNum >= 1000000) {
            busiCosts = 0;
            busiNum = 0;
            perfBusiNum = 0;
            goodBusiNum = 0;
            comBusiNum = 0;
            slowBusiNum = 0;
            badBusiNum = 0;
            maxBusiCosts = 999;
        }

        busiNum++;
        busiCosts += costtime;
        maxBusiCosts = costtime > maxBusiCosts ? costtime : maxBusiCosts;
        minBusiCost = costtime < minBusiCost ? costtime : minBusiCost;

        if (costtime < 10) {
            perfBusiNum++;
        } else if (costtime < 20) {
            goodBusiNum++;
        } else if (costtime < 200) {
            comBusiNum++;
        } else if (costtime < 500) {
            slowBusiNum++;
        } else {
            badBusiNum++;
        }


    }

    public synchronized static void calTransCost(long startTime, long endTime) {
        transNum++;
        long cost = endTime - startTime;
        transCosts += cost;
        maxTransCost = cost > maxTransCost ? cost : maxTransCost;
        minTransCost = cost < minTransCost ? cost : minTransCost;
        if (cost > 100) {

        } else if (cost > 20) {

        }
    }

    public synchronized static void expireTransNum() {
        transExpireNum++;
    }


    public static void startTrans(String transId, long curtime) {
        if (!monitorMap.containsKey(transId)) {
            TransMonitor transMon = new TransMonitor();
            monitorMap.put(transId, transMon);
            transMon.firsttime = curtime;
        }
    }

    public static void endTrans(String transId, long curtime) {
        if (monitorMap.containsKey(transId)) {
            monitorMap.get(transId).recoktime = curtime;
            //monitorMap.remove(transId);
        }
    }

    public static void busiTrans(String transId, long curtime) {
        if (monitorMap.containsKey(transId)) {
            monitorMap.get(transId).busitime = curtime;
        }

    }

    public synchronized static void startBusi() {
        busiStartNum++;
    }

    public static void callTrans(String transId, long curtime) {
        if (monitorMap.containsKey(transId)) {
            monitorMap.get(transId).calltime = curtime;
        }
    }

    public static void callokTrans(String transId, long curtime) {
        if (monitorMap.containsKey(transId)) {
            monitorMap.get(transId).calloktime = curtime;
        }
    }

    public static void expireTrans(String transId, long curtime) {
        if (monitorMap.containsKey(transId)) {
            TransMonitor monobj = monitorMap.get(transId);
            StringBuilder moninfo = new StringBuilder();
            moninfo.append("\n*********TRANS EXPIRED***************");
            moninfo.append("\n****firsttime").append(monobj.firsttime);
            moninfo.append("\n*****reoktime").append(monobj.recoktime);
            moninfo.append("\n*****busitime").append(monobj.busitime);
            moninfo.append("\n*****expiretime").append(curtime);
            moninfo.append("\n************************");
            logger.error(moninfo.toString());
            expireTransNum();
        } else {
            logger.error("*********调用完成，没有监控信息" + transId);
        }
    }

    public static int getTransDebug(long uid) {
        return 1;
    }

    public static TransMonitor respTrans(String transId, long curtime) {
        if (monitorMap.containsKey(transId)) {
            TransMonitor monobj = monitorMap.get(transId);
            monobj.resptime = curtime;
            calTransCost(monobj.firsttime, curtime);
            /*
            StringBuilder moninfo = new StringBuilder();
            moninfo.append("\n**********TRANS SUCCESSED**************");
            moninfo.append("\n****firsttime").append(monobj.firsttime);
            moninfo.append("\n*****reoktime").append(monobj.recoktime);
            moninfo.append("\n*****busitime").append(monobj.busitime);
            moninfo.append("\n*****calltime").append(monobj.calltime);
            moninfo.append("\n****caloktime").append(monobj.calloktime);
            moninfo.append("\n*****resptime").append(curtime);
            moninfo.append("\n************************");
            logger.error(moninfo.toString());
            */
            return monobj;
        } else {
            return null;
            //logger.error("*********调用完成，没有监控信息"+transId);
        }
    }


    public static String getMonitorStatus() {
        StringBuilder monitorinfo = new StringBuilder();
        monitorinfo.append("\n%%%%%%%%%%%%%%%%%%%%%%%%%%");
        monitorinfo.append("\n%%%%%%receive---threadNum:").append(receiveThreadNum);
        monitorinfo.append(";blocknum:").append(recvBlockNum);
        monitorinfo.append(";acknum:").append(recvAckNum);
        monitorinfo.append(";erracknum:").append(errAckNum);
        monitorinfo.append(";blockcost:");
        if (recvBlockNum > 0) {
            monitorinfo.append(recvBlockCost / recvBlockNum);
        }
        monitorinfo.append(";maxCost:").append(maxRecvBlockCost);
        monitorinfo.append(";minCost:").append(minRecvBlockCost);

        monitorinfo.append("\n%%%%%%busi---threadNum:").append(busiThreadNum);
        monitorinfo.append(";startNum:").append(busiStartNum);
        monitorinfo.append(";doingNum:").append(busiDoneNum);
        monitorinfo.append(";businum:").append(busiNum);
        monitorinfo.append("(perf:").append(perfBusiNum);
        monitorinfo.append(";good:").append(goodBusiNum);
        monitorinfo.append(";com:").append(comBusiNum);
        monitorinfo.append(";slow:").append(slowBusiNum);
        monitorinfo.append(";bad:").append(badBusiNum).append(")");
        monitorinfo.append(";cost:");
        if (busiNum > 0) {
            monitorinfo.append(busiCosts / busiNum);
        }
        monitorinfo.append(";maxCost:").append(maxBusiCosts);
        monitorinfo.append(";minCost:").append(minBusiCost);

        monitorinfo.append("\n%%%%%%transNum").append(transNum);
        monitorinfo.append(";transExpire:").append(transExpireNum);
        monitorinfo.append(";transCost:");
        if (transNum > 0) {
            monitorinfo.append(transCosts / transNum);
        }
        monitorinfo.append(";maxCost:").append(maxTransCost);
        monitorinfo.append(";minCost:").append(minTransCost);

        monitorinfo.append("\n%%%%%%sendBlock--sendnum:").append(sndBlockNum);
        monitorinfo.append(";succnum:").append(sndBlockAckNum);
        monitorinfo.append(";resendNum:").append(resendBlockNum);
        monitorinfo.append(";expireNum:").append(expireBlockNum);
        monitorinfo.append("\n%%%%%%%%%%%%%%%%%%%%%%%%%%");
        return monitorinfo.toString();
    }
}
